package file.sftp;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Date;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

public class SFtpUtil {

	private String ip;

	private String user;

	private String pwd;

	private int port = 22;

	private Session session;
	private ChannelSftp channel;

	private String rootPath;

	/**
	 * 采用默认端口构造
	 * 
	 * @param ip ftp服务器IP<br>
	 * @param user ftp帐号<br>
	 * @param pwd ftp 帐号密码<br>
	 * */
	public SFtpUtil(String ip, String user, String pwd) {
		this.ip = ip;
		this.user = user;
		this.pwd = pwd;
	}

	/**
	 * 采用默认端口构造
	 * 
	 * @param ip ftp服务器IP<br>
	 * @param port 服务器端口<br>
	 * @param user ftp帐号<br>
	 * @param pwd ftp 帐号密码<br>
	 * */
	public SFtpUtil(String ip, int port, String user, String pwd) {
		this.ip = ip;
		this.user = user;
		this.pwd = pwd;
		this.port = port;
	}

	/**
	 * 连接ftp服务器<br>
	 * 
	 * @return 是否连接成功<br>
	 */
	public boolean connect() {
		try {
			// 创建JSch对象
			JSch jsch = new JSch();

			// 根据用户名，主机ip，端口获取一个Session对象
			session = jsch.getSession(user, ip, port);

			// 配置参数
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");

			// 为Session对象设置properties
			session.setConfig(config);

			// 设置密码
			session.setPassword(pwd);

			// 设置timeout时间
			session.setTimeout(10000);

			// 通过Session建立链接
			session.connect();
			

			// 打开SFTP通道
			channel = (ChannelSftp) session.openChannel("sftp");

			// 建立SFTP通道的连接
			channel.connect();

			// 登录根目录
			rootPath = channel.pwd();
			return true;
		} catch (Exception e) {
			
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 断开ftp服务器<br>
	 *
	 * @return 是否连接成功<br>
	 */
	public boolean disconnect() {
		try {
			if (channel != null && channel.isConnected()) {
				channel.disconnect();
				
			}
			if (session != null && session.isConnected()) {
				session.disconnect();
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * 将文件上传到远程服务器<br>
	 * 
	 * @param String
	 *            data 写入的数据<br>
	 * @param String
	 *            remoteDir 存放目录<br>
	 * @param remoreFileName
	 *            存放文件名<br>
	 * @return int 0:上传成功；1：目录无权限；2：上传文件 失败；
	 * */
	public int upload(File localFile, String remoteDir, String remoteFileName)
			throws Exception {
		// 检查目录是否有权限
		if (!checkPath(remoteDir)) {
			
			return 1;
		}

		// 判断目录是否存在
		if (!isDirExist(remoteDir)) {
			
			if (makeDir(remoteDir)) {
				
			} else {
				
				return 2;
			}
		}
		try {
			channel.cd(remoteDir);
		} catch (Exception e) {
			return 2;
		}
		try {
			channel.put(Files.newInputStream(localFile.toPath()), remoteFileName);
			return 0;
		} catch (Exception e) {
			return 2;
		}
	}

	/**
	 * 将指定字符串上传到远程服务器<br>
	 * 
	 * @param String
	 *            data 写入的数据<br>
	 * @param String
	 *            remoteDir 存放目录<br>
	 * @param remoreFileName
	 *            存放文件名<br>
	 * @return int 0:上传成功；1：目录无权限；2：上传文件 失败；
	 * */
	public int upload(String data, String remoteDir, String remoteFileName)
			throws Exception {
		// 检查目录是否有权限
		if (!checkPath(remoteDir)) {
			
			return 1;
		}

		// 判断目录是否存在
		if (!isDirExist(remoteDir)) {
			
			if (makeDir(remoteDir)) {
				
			} else {
				
				return 2;
			}
		}
		try {
			channel.cd(remoteDir);
		} catch (Exception e) {
			e.printStackTrace();
			return 2;
		}
		InputStream input = new ByteArrayInputStream(data.getBytes("utf-8"));
		try {
			channel.put(input, remoteFileName, ChannelSftp.OVERWRITE);
			return 0;
		} catch (Exception e) {
			e.printStackTrace();
			return 2;
		}
	}

	/**
	 * 检查目录否存在
	 * 
	 * @param dir
	 * @return
	 */
	public boolean isDirExist(String dir) {
		// 将工作目录切换到指定目录
		try {
			channel.cd(dir);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 检测目录是否合法（给定的目录必须在FTP根目录之下）<br>
	 * */

	public boolean checkPath(String dir) {
		// 判断给定目录是以FTP工作目录开头
		if (dir != null && dir.startsWith(this.rootPath)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 在服务器上创建目录<br>
	 * 
	 * @param String
	 *            remoteDir 远程目录<br>
	 * */
	protected boolean makeDir(String dir) throws Exception {
		String workingDirectory = channel.pwd();
		// 判断给定目录是以FTP工作目录开头
		if (dir != null && dir.startsWith(this.rootPath)) {
			// 相对路径
			String relativePath = dir.substring(this.rootPath.length());
			String subdir = new String();
			StringTokenizer st = new StringTokenizer(relativePath, "/");
			while (st.hasMoreTokens()) {
				subdir = st.nextToken();
				boolean isExist = true;
				try {
					channel.cd(subdir);
					isExist = true;
				} catch (Exception e) {
					isExist = false;
				}
				if (!isExist) {
					channel.mkdir(subdir);
					channel.cd(subdir);
				}
			}
			if (workingDirectory != null) {
				channel.cd(workingDirectory);
			}
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 检测文件是否存在
	 * */
	@SuppressWarnings("unchecked")
	public boolean isFileExist(String filePath) throws Exception {
		try {
			Vector names = channel.ls(filePath);
			if (names != null && names.size() > 0) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}

	}

	/**
	 * 文件重命名
	 * */
	public boolean renameFile(String fromPath, String toPath) throws Exception {
		channel.rename(fromPath, toPath);
		return true;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			SFtpUtil ftpUtil = new SFtpUtil("10.1.252.106", "aiuap", "aiuap");
			String fullPath = "/home/aiuap/zhaoyong/zy/zy/test.sh";
			if (ftpUtil.connect()) {
				// 判断文件是否存在
				boolean isExist = ftpUtil.isFileExist(fullPath);
				// 如果文件存在，则将文件重命名
				if (isExist) {
					ftpUtil.renameFile(fullPath, fullPath + "."
							+ Long.toString((new Date()).getTime()));
				}
				int rs = ftpUtil.upload("HelloWord",
						"/home/aiuap/zhaoyong/zy/zy", "test.sh");
				System.err.println(rs);

				ftpUtil.disconnect();
			} else {
				System.err.println("no connect");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	public Vector<LsEntry> listFiles(String directory) throws SftpException {
		return channel.ls(directory);
	} 
	
	public InputStream download(String file) throws SftpException{
		return channel.get(file);
	}
	
	public InputStream download(String file,String dir) throws SftpException{
		channel.cd(dir);
		return channel.get(file);
	}

	public void remove(String file,String dir) throws SftpException{
		channel.cd(dir);
		channel.rm(file);
	}


	public void remove(String file) throws SftpException{
		channel.rm(file);
	}


	public void cd(String dir) throws SftpException{
		channel.cd(dir);
	}

}
